package eu.catengine.common.manager;

import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;

import javax.microedition.khronos.opengles.GL10;

import android.content.res.AssetManager;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import eu.catengine.common.iface.IDisposable;
import eu.catengine.common.iface.IManager;
import eu.catengine.graphic.Texture;

/**
 * Manager odpowiedzialny za przechowywanie danych tekstur.
 * 
 * @author mbienkowski
 */
public class TextureManager implements IDisposable, IManager<TextureManager, Texture>
{
    private static volatile TextureManager mInstance;
    private HashMap<String, Texture> mTextureHashMap;
    private GL10 mGL;
    private AssetManager mAssetManager;

    private TextureManager()
    {
	mTextureHashMap = new HashMap<String, Texture>();
    }

    /**
     * Zwraca instanację managera.
     */
    public static TextureManager getInstance()
    {
	if (mInstance == null)
	{
	    mInstance = new TextureManager();
	}
	return mInstance;
    }

    /**
     * Ładuje teksturę do managera.<br>
     * <br>
     * Po wczytaniu odwołujemy się do obiektu po jego nazwie, bez rozszerzenia.
     * 
     * @param pathName
     *            <code>String</code> Ścieżka pliku z katalogu "Assets/".
     * @return <code>Texture</code> Zwraca stworzony obiekt.
     */
    public Texture loadTexture(String pathName)
    {
	if (pathName.equals(""))
	{
	    return null;
	}

	String[] filePathArray = pathName.split("/");
	String fileName = filePathArray[filePathArray.length - 1];

	String[] fileNameArray = fileName.split("\\.");
	String name = fileNameArray[0];

	if (!mTextureHashMap.containsKey(name))
	{
	    Bitmap loadedBitmap = getBitmapFromAsset(pathName);

	    if (loadedBitmap == null)
	    {
		return null;
	    }

	    Texture internalTex = new Texture(mGL, loadedBitmap);
	    mTextureHashMap.put(name, internalTex);
	}

	return get(name);
    }

    /**
     * Ładuje teksturę do managera.<br>
     * <br>
     * Po wczytaniu odwołujemy się do obiektu po jego nazwie, bez rozszerzenia.
     * 
     * @param name
     *            <code>String</code> Nazwa wczytywanej tekstury.
     * @param bitmap
     *            <code>Bitmap</code> Bitmapa względem której tworzona jest
     *            tekstura.
     * @return <code>Texture</code> Utworzony obiekt tekstury.
     */
    public Texture loadTexture(String name, Bitmap bitmap)
    {
	if (!mTextureHashMap.containsKey(name))
	{
	    Texture internalTex = new Texture(mGL, bitmap);
	    mTextureHashMap.put(name, internalTex);
	}

	return get(name);
    }

    private Bitmap getBitmapFromAsset(String pathName)
    {
	try
	{
	    InputStream istr = mAssetManager.open(pathName);
	    Bitmap bitmap = BitmapFactory.decodeStream(istr);
	    return bitmap;
	}
	catch (IOException e)
	{
	    e.printStackTrace();
	}

	return null;
    }

    /**
     * Ustawia instancję biblioteki OpenGL dla managera. <br>
     * <b>Metoda wywoływana automatycznie</b><br>
     * Nie należy wywoływać metody ręcznie.
     */
    public void setGL(GL10 gl)
    {
	this.mGL = gl;
    }

    /**
     * Ustawia managera zasobów zewnętrznych dla managera.<br>
     * <b>Metoda wywoływana automatycznie</b><br>
     * Nie należy wywoływać metody ręcznie.
     */
    public void setAssetManager(AssetManager assetManager)
    {
	this.mAssetManager = assetManager;
    }

    @Override
    public Texture get(String name)
    {
	return mTextureHashMap.get(name);
    }

    @Override
    public void remove(String name)
    {
	mTextureHashMap.remove(name);
    }

    @Override
    public void remove(Texture object)
    {
	mTextureHashMap.remove(object);
    }

    @Override
    public void dispose()
    {
	mTextureHashMap.clear();

	mGL = null;
	mAssetManager = null;
	mInstance = null;
    }
}
